﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DicomLibrary.Parsing
{
    public class ExplicitLittleEndianParser : DParser
    {
        public override DValueRepresentation ParseNextValueRepresentation()
        {
            //Big endian representation of VR
            short vrbe = BitConverter.ToInt16(BinaryReader.ReadBytes(2), 0);
            //Little endian representation (VR is always little endian since it's a string)
            short vr = (short)(((vrbe & 0xff) << 8) | ((vrbe >> 8) & 0xff));

            if (Enum.IsDefined(typeof(DValueRepresentation), vr))
            {
                return (DValueRepresentation)vr;
            }
            else
            {
                throw new NotImplementedException();
            }
        }

        public override DTag ParseNextTag()
        {
            return new DTag(
                BinaryReader.ReadInt16(),
                BinaryReader.ReadInt16()
                );
        }

        public override object ParseNextValue(DValueRepresentation valueRepresentation, int valueLength)
        {
            switch (valueRepresentation)
            {
                case DValueRepresentation.UnsignedShort:
                    if (valueLength == 2)
                    {
                        return BinaryReader.ReadUInt16();
                    }
                    else
                    {
                        //This has to do with valuemultiplicity!
                        //This is not the proper way, we should do a for loop for every valuemultiplicity
                        //Then we return either 1 or an array (or list??) to get it
                        ushort[] shortValues = new ushort[valueLength / 2];
                        for (int i = 0; i < valueLength; i += 2)
                        {
                            shortValues[i / 2] = BinaryReader.ReadUInt16();
                        }
                        return shortValues;
                    }
                case DValueRepresentation.AttributeTag:
                case DValueRepresentation.UnsignedLong:
                    return BinaryReader.ReadInt32();
                case DValueRepresentation.SequenceOfItems:
                    throw new NotImplementedException();
                case DValueRepresentation.OtherByte:
                    return BinaryReader.ReadBytes(valueLength);
                case DValueRepresentation.OtherWord:
                    ushort[] wordValues = new ushort[valueLength / 2];
                    for (int i = 0; i < valueLength; i += 2)
                    {
                        wordValues[i / 2] = BinaryReader.ReadUInt16();
                    }
                    return wordValues;
                case DValueRepresentation.UniqueIdentifier:
                    return ASCIIEncoding.ASCII.GetString(BinaryReader.ReadBytes(valueLength)).TrimEnd('\0');
                case DValueRepresentation.SignedShort:
                case DValueRepresentation.ApplicationEntity:
                case DValueRepresentation.CodeString:
                case DValueRepresentation.Date:
                case DValueRepresentation.Time:
                case DValueRepresentation.LongString:
                case DValueRepresentation.PersonName:
                case DValueRepresentation.AgeString:
                case DValueRepresentation.DecimalString:
                case DValueRepresentation.IntegerString:
                case DValueRepresentation.LongText:
                case DValueRepresentation.DateTime:
                case DValueRepresentation.ShortString:
                case DValueRepresentation.ShortText:
                    return ASCIIEncoding.ASCII.GetString(BinaryReader.ReadBytes(valueLength));
                default:
                    throw new NotImplementedException();
            }
        }

        public override int ParseNextValueLength(DValueRepresentation valueRepresentation)
        {
            switch (valueRepresentation)
            {
                case DValueRepresentation.OtherByte:
                case DValueRepresentation.OtherWord:
                    BinaryReader.ReadBytes(2); // Explicit has 2 extra ones
                    return BinaryReader.ReadInt32();
                case DValueRepresentation.SequenceOfItems:
                    throw new NotImplementedException();
                default:
                    return BinaryReader.ReadInt16();
            }
        }

        public ExplicitLittleEndianParser(System.IO.BinaryReader binaryReader) : base(binaryReader) { }
        public ExplicitLittleEndianParser(DTransferSyntax transferSyntax, System.IO.BinaryReader binaryReader) : base(transferSyntax, binaryReader) { }

    }
}
